package com.enbatis.mybatisplugs.base;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.enbatis.mybatisplugs.commons.sql.Wrapper;
import com.enbatis.mybatisplugs.commons.utils.IdWorker;
import com.enbatis.mybatisplugs.commons.utils.LineHumpUtil;
import com.enbatis.mybatisplugs.commons.utils.ReflectionKit;
import com.enbatis.mybatisplugs.plugin.Pages;
import org.apache.commons.collections4.ListUtils;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.List;

public class BaseServiceImpl<M extends  BaseMapper<T>,T> implements IBaseService<T>{


    @Autowired
    protected M baseMapper;


    @Autowired
    SqlSessionTemplate sqlSessionTemplate;

    private Class<T> entityClass;
    String className=   "";
    public BaseServiceImpl() {
        this.entityClass = currentModelClass();
        this.className= LineHumpUtil.humpToLine(entityClass.getSimpleName());
    }

    protected Class<T> currentModelClass() {
        return ReflectionKit.getSuperClassGenricType(this.getClass(), 1);
    }


    @Override
    public T getById(Serializable id) {
        return baseMapper.getById(LineHumpUtil.humpToLine(entityClass.getSimpleName()),id);
    }


    public int deleteById(Serializable id){
        return baseMapper.deleteById(LineHumpUtil.humpToLine(entityClass.getSimpleName()),id);
    }


    @Override
    public int updateById(T bean) {

        return baseMapper.updateById(className,bean);
    }

    @Override
    public List<T> list(Wrapper<T> wrapper) {
        return baseMapper.list(wrapper);
    }


    @Override
    public Pages<T> page(Page<T> page, Wrapper<T> wrapper) {
        Page returnPage= PageHelper.startPage(page.getPageNum(),page.getPageSize(),page.getOrderBy());
        baseMapper.page(wrapper);
        Pages<T> pages=new Pages<>(returnPage);
        return pages;
    }


    @Override
    public  int selectCount(Wrapper<T> wrapper){
      return   baseMapper.selectCount(wrapper);
    }


    @Override
    public int update(T entity, Wrapper<T> wrapper) {
        return baseMapper.update(entity,wrapper);
    }

    @Override
    public T insert(T entity){

        try {
          Method method= entityClass.getMethod("getId");
            if (method.invoke(entity)==null){
                Method methodSet= entityClass.getMethod("setId",Long.class);
                Method methodSetDeleted= entityClass.getMethod("setDeleted",Integer.class);
                if (null!=methodSetDeleted){
                    methodSetDeleted.invoke(entity, 0);
                }

                methodSet.invoke(entity, IdWorker.getId());
            }
        }catch (Exception e){
            e.printStackTrace();
        }


        baseMapper.insert(entity);
        return entity;
    }



    @Transactional(rollbackFor = Exception.class)
    public int saveBatch(List<T> entityList){
        try {
            Method method= entityClass.getMethod("getId");
            Method methodSet= entityClass.getMethod("setId",Long.class);
            for (T entity:entityList) {
                if (method.invoke(entity)==null){
                    methodSet.invoke(entity, IdWorker.getId());
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }

        int size=0;
        List<List<T>> lists= ListUtils.partition(entityList,500);
        for (List<T> list:lists) {
            size+=baseMapper.saveBatch(list,entityClass);

        }
        return size;
    }




}
